/*
 * Log.java
 *
 */

package net.kernub.kebcore.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.CloseEvent;

import java.util.ArrayList;

public class Log
{
	public final static int T_DEBUG = 0;
	public final static int T_INFO = 1;
	public final static int T_ERROR = 2;
	public final static int T_FATAL = 3;

	// TODO: use a PopupPanel instead of a LayoutPanel instead?
	private class LogPopup extends PopupPanel
	{
		private class PositionCb implements PopupPanel.PositionCallback
		{
			private LogPopup popup = null;

			public PositionCb( final LogPopup popup )
			{
				this.popup = popup;
			}

			public void setPosition( int offsetWidth, int offsetHeight )
			{
				GWT.log( "width: " + offsetWidth + " height: " + offsetHeight, null );
				int left = (Window.getClientWidth() - offsetWidth) / 2;
				int top = 10;
				this.popup.setPopupPosition( left, top );
			}
		};

		//private final VerticalPanel logsPanel = new VerticalPanel();
		private final FlexTable logsTable = new FlexTable();

		private PositionCb positionCallback = null;

		public LogPopup()
		{
			super( true );

			final VerticalPanel panel = new VerticalPanel();
			panel.add( new HTML( "<b> Logs </b>" ) );
			panel.add( this.logsTable );

			final CloseHandler<PopupPanel> closeHandler = new CloseHandler<PopupPanel>() {
				public void onClose( CloseEvent<PopupPanel> event ) {
					logsTable.clear( true );
					int i = logsTable.getRowCount();
					while( --i >= 0 ) logsTable.removeRow( i );
				}
			};

			positionCallback = new PositionCb( this );

			this.setWidget( panel );
			this.setTitle( "Logs" );
			this.setAutoHideEnabled( true );
			this.setAnimationEnabled( true );
			this.setGlassEnabled( true );
			this.addCloseHandler( closeHandler );
		}

		public void showLogs()
		{
			final LogPopup _this = this;
			final PopupPanel.PositionCallback callback = new PopupPanel.PositionCallback() {
				public void setPosition( int offsetWidth, int offsetHeight ) {
					int left = (Window.getClientWidth() - offsetWidth) / 2;
					int top = 10;
					_this.setPopupPosition( left, top );
				}
			};

			this.setPopupPositionAndShow( callback );
		}

		private final String getLogStrType( final int ty )
		{
			switch( ty )
			{
				case T_DEBUG: return "DEBUG"; 
				case T_INFO: return "INFO"; 
				case T_ERROR: return "ERROR"; 
				case T_FATAL: return "FATAL"; 
			}
			return "UNKNOWN";
		}

		public void add( final int type, final String msg )
		{
			final int row = logsTable.getRowCount();
			final String tyStr = "[" + getLogStrType( type ) + "]";
			logsTable.setText( row, 0, tyStr );
			logsTable.setText( row, 1, msg );

			GWT.log( tyStr + ": " + msg, null );

			// need to show at each new entry, so size is recalculated
			this.showLogs();
		}

		public void add( final int type, final Widget msg )
		{
			final int row = logsTable.getRowCount();
			final String tyStr = "[" + getLogStrType( type ) + "]";
			logsTable.setText( row, 0, tyStr );
			logsTable.setWidget( row, 1, msg );

			GWT.log( tyStr + ": " + msg, null );

			// need to show at each new entry, so size is recalculated
			this.showLogs();
		}

		public void add( final int type, final String msg,
										 final String className, final String methodName,
										 final String fileName, final int lineNo )
		{
			final int row = logsTable.getRowCount();
			final String tyStr = "[" + getLogStrType( type ) + "]";
			logsTable.setText( row, 0, tyStr );
			logsTable.setText( row, 1, msg );
			logsTable.setText( row, 2, className+"::"+methodName );
			logsTable.setText( row, 3, fileName );
			logsTable.setText( row, 4, ""+lineNo );

			GWT.log( tyStr + ": " + msg, null );

			// need to show at each new entry, so size is recalculated
			this.showLogs();
		}
	};

	private static Log instance = null;

	private final LogPopup popup = new LogPopup();

	public Log()
	{
	}

	public static Log inst()
	{
		return Log.instance;
	}

	public static void create()
	{
		if( instance == null )
		{
			instance = new Log();
		}
	}

	public static void dbg( final String msg )
	{
		GWT.log( "[DEBUG]: " + msg, null );
	}

	public static void debug( final String msg )
	{
		Log.instance.popup.add( T_DEBUG, msg );
	}

	public static void debugHtml( final String msg )
	{
		Log.instance.popup.add( T_DEBUG, new HTML(msg) );
	}

	public static void info( final String msg )
	{
		Log.instance.popup.add( T_INFO, msg );
	}

	public static void infoHtml( final String msg )
	{
		Log.instance.popup.add( T_INFO, new HTML(msg) );
	}

	public static void error( final String msg )
	{
		Log.instance.popup.add( T_ERROR, msg );
	}

	public static void errorHtml( final String msg )
	{
		Log.instance.popup.add( T_ERROR, new HTML(msg) );
	}

	public static void fatal( final String msg )
	{
		Log.instance.popup.add( T_FATAL, msg );
	}

	public static void fatalHtml( final String msg )
	{
		Log.instance.popup.add( T_FATAL, new HTML(msg) );
	}

	public static void add( final int type, final String msg )
	{
		Log.instance.popup.add( type, msg );
	}

	public static void add( final int type, final String msg, 
													final String className, final String methodName, 
													final String fileName, final int lineNo )
	{
		Log.instance.popup.add( type, msg, className, methodName, fileName, lineNo );
	}
};

